#!/usr/bin/evn python
# -*- coding: utf-8 -*-
"""
-------------------------------------------------
File Name： ApiException
Description :
Author : 'Mark.Wei'
date： 2022/6/1
-------------------------------------------------
Change Activity:
2022/6/1:
-------------------------------------------------
"""

from fastapi import FastAPI, Request
from starlette.exceptions import HTTPException as StarletteHTTPException
from fastapi.exceptions import HTTPException as FastapiHTTPException
from fastapi.exceptions import RequestValidationError
from pydantic.errors import *
import traceback

from ml import logger
from ml.micro_service.exception.BizException import BizException
from ml.micro_service.exception.singleton_util import singleton
from ml.micro_service.response.ApiResponse import ApiResponse
from ml.micro_service.response.ParamErrorResponse import ParamErrorResponse


async def request_validation_error_handler(request: Request, exc: RequestValidationError):
    if isinstance(exc.raw_errors[0].exc, IntegerError):
        pass
    elif isinstance(exc.raw_errors[0].exc, MissingError):
        pass

    errors = exc.errors()
    request_body = exc.body

    log = {
        'status_code': 400,
        'message': errors,
        'body': request_body
    }
    logger.error(log)

    response = ParamErrorResponse({"body": request_body, "detail": errors})

    return response


async def starlette_http_exception_handler(request: Request, exc: StarletteHTTPException):
    log = {
        'status_code': exc.status_code,
        'message': exc.detail,
        'trace': traceback.format_exc()
    }
    logger.error(log)

    return ApiResponse(10001, exc.detail, None, exc.status_code)


async def fastapi_http_exception_handler(request: Request, exc: FastapiHTTPException):
    log = {
        'status_code': exc.status_code,
        'message': exc.detail,
        'trace': traceback.format_exc()
    }
    logger.error(log)

    return ApiResponse(10001, exc.detail, None, exc.status_code)


async def biz_exception_handler(request: Request, exc: BizException):
    log = {
        'code': exc.code,
        'message': exc.message,
        'trace': traceback.format_exc()
    }
    logger.error(log)

    return ApiResponse(exc.code, exc.message, None, None)


def init_app(app: FastAPI):
    app.add_exception_handler(RequestValidationError, handler=request_validation_error_handler)
    app.add_exception_handler(StarletteHTTPException, handler=starlette_http_exception_handler)
    app.add_exception_handler(FastapiHTTPException, handler=fastapi_http_exception_handler)
    app.add_exception_handler(BizException, handler=biz_exception_handler)


@singleton
class ApiExceptionHandler:
    def __init__(self, app=None, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if app is not None:
            init_app(app)
